package com.sdsmdg.harjot.vectormaster;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Path;
import ohos.agp.utils.Matrix;
import ohos.app.Context;

import com.sdsmdg.harjot.vectormaster.models.ClipPathModel;
import com.sdsmdg.harjot.vectormaster.models.GroupModel;
import com.sdsmdg.harjot.vectormaster.models.PathModel;
import com.sdsmdg.harjot.vectormaster.models.VectorModel;
import com.sdsmdg.harjot.vectormaster.utilities.Utils;

import java.io.Serializable;

/**
 * VectorMasterView
 */
public class VectorMasterView extends Component implements Component.DrawTask {
    private String path;
    private final String FILE_PATH = "entry/resources/rawfile/";
    private VectorModel vectorModel;
    private Context context;
    private Matrix scaleMatrix;
    private int width = 0;
    private int height = 0;
    private int vectorXml = 0;

    private float scaleRatio;
    private float strokeRatio;

    public VectorMasterView(Context context) {
        super(context);
        this.context = context;
    }

    public VectorMasterView(Context context, AttrSet attrs) {
        super(context, attrs);
        this.context = context;
        init(attrs);
    }

    public VectorMasterView(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(attrs);
    }
    void init(AttrSet attrs) {
        new StyledAttributes(attrs);

        if (vectorXml != 0) {
            vectorModel = new XmlParser().buildVectorModel(context, vectorXml);
        } else {
            vectorModel = new XmlParser().buildVectorModel(context, path);
        }

        onSizeChanged();
        addDrawTask(this);
        update();
    }

    private void onSizeChanged() {
        height = getHeight();
        width = getWidth();

        buildScaleMatrix();
        scaleAllPaths();
        scaleAllStrokes();
    }

    @Override
    public void estimateSize(int widthEstimatedConfig, int heightEstimatedConfig) {
        super.estimateSize(widthEstimatedConfig, heightEstimatedConfig);
        if (widthEstimatedConfig != 0 && heightEstimatedConfig != 0) {
            width = widthEstimatedConfig;
            height = heightEstimatedConfig;

            buildScaleMatrix();
            scaleAllPaths();
            scaleAllStrokes();
        }
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        width = component.getWidth();
        height = component.getHeight();

        if (vectorModel == null) {
            return;
        }

        setAlpha(vectorModel.getAlpha());

        vectorModel.drawPaths(canvas);
    }

    void buildScaleMatrix() {
        scaleMatrix = new Matrix();

        scaleMatrix.postTranslate(width / 2 - vectorModel.getViewportWidth() / 2,
                height / 2 - vectorModel.getViewportHeight() / 2);

        float widthRatio = width / vectorModel.getViewportWidth();
        float heightRatio = height / vectorModel.getViewportHeight();
        float ratio = Math.min(widthRatio, heightRatio);

        scaleRatio = ratio;

        scaleMatrix.postScale(ratio, ratio, width / 2, height / 2);
    }

    void scaleAllPaths() {
        vectorModel.scaleAllPaths(scaleMatrix);
    }

    void scaleAllStrokes() {
        strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight());
        vectorModel.scaleAllStrokeWidth(strokeRatio);
    }

    /**
     * Get full path
     *
     * @return fullPath
     */
    public Path getFullPath() {
        Path fullPath = null;
        if (vectorModel != null) {
            fullPath = vectorModel.getFullpath();
        }
        return fullPath;
    }

    /**
     * Get GroupModel from model name
     *
     * @param name model name
     * @return GroupModel
     */
    public GroupModel getGroupModelByName(String name) {
        GroupModel gModel = null;
        for (GroupModel groupModel : vectorModel.getGroupModels()) {
            if (Utils.isEqual(groupModel.getName(), name)) {
                return groupModel;
            } else {
                gModel = groupModel.getGroupModelByName(name);
                if (gModel != null) {
                    return gModel;
                }
            }
        }
        return gModel;
    }

    /**
     * Get PathModel from model name
     *
     * @param name model name
     * @return PathModel
     */
    public PathModel getPathModelByName(String name) {
        PathModel pModel = null;
        for (PathModel pathModel : vectorModel.getPathModels()) {
            if (Utils.isEqual(pathModel.getName(), name)) {
                return pathModel;
            }
        }
        for (GroupModel groupModel : vectorModel.getGroupModels()) {
            pModel = groupModel.getPathModelByName(name);
            if (pModel != null && Utils.isEqual(pModel.getName(), name)) {
                return pModel;
            }
        }
        return pModel;
    }

    /**
     * Get ClipPathModel from model name
     *
     * @param name model name
     * @return ClipPathModel
     */
    public ClipPathModel getClipPathModelByName(String name) {
        ClipPathModel cModel = null;
        for (ClipPathModel clipPathModel : vectorModel.getClipPathModels()) {
            if (Utils.isEqual(clipPathModel.getName(), name)) {
                return clipPathModel;
            }
        }
        for (GroupModel groupModel : vectorModel.getGroupModels()) {
            cModel = groupModel.getClipPathModelByName(name);
            if (cModel != null && Utils.isEqual(cModel.getName(), name)) {
                return cModel;
            }
        }
        return cModel;
    }

    /**
     * Update view
     */
    public void update() {
        invalidate();
    }

    public float getScaleRatio() {
        return scaleRatio;
    }

    public float getStrokeRatio() {
        return strokeRatio;
    }

    public Matrix getScaleMatrix() {
        return scaleMatrix;
    }

    /**
     * Parse Style attributes
     */
    private class StyledAttributes {
        private String vectorSrc = "vector_src";

        StyledAttributes(AttrSet attrs) {
            String value = attrs.getAttr(vectorSrc).isPresent() ? attrs.getAttr(vectorSrc).get().getStringValue() : null;
            if (value != null) {
                String[] parts = value.split(":");
                if (parts[0].equalsIgnoreCase("$graphic")) {
                    vectorXml = Integer.parseInt(parts[1]);
                } else if (parts[0].equalsIgnoreCase("$raw")) {
                    path = FILE_PATH + parts[1] + ".xml";
                }
            }
        }
    }
}
